package jp.sourceforge.akjrcp.dropsomething;

import java.io.File;

import jp.sourceforge.akjrcp.akj_betas.Akj_betasPlugin;
import jp.sourceforge.akjrcp.akj_betas.Messages;
import jp.sourceforge.akjrcp.ffmpeg.FFMpegExecuter;
import jp.sourceforge.akjrcp.ffmpeg.FFMpegOptions;
import jp.sourceforge.akjrcp.ffmpeg.FFMpegPreference;
import jp.sourceforge.akjrcp.ffmpeg.FFMpegUI;
import jp.sourceforge.akjrcp.ffmpeg.FFMpegUtils;
import jp.sourceforge.akjrcp.ui.DirectryBasedExecuterListener;
import jp.sourceforge.akjrcp.ui.FileOverwriteControler;

import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CCombo;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Scale;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.ViewPart;

public class MPEGConvertTabBuilder implements IDropSomething{

	private FileOverwriteControler fileOverwriteControler;
	
	public static final String TYPE_SELECT="type_select";
	public static final String AVISYNTH="avisynth";
	public static final String VIDEO_BITRATE="video_bitrate";
	public static final String ASPECT_RATIO="aspect_ratio";
	public static final String TWO_PASS="twopass";
	public static final String MPEGCONVERT="mpegconvert";
	public static final String DEINTERLACE="deinterlace";
	
	private DropsomethingTab dtab;
	private CTabItem tabItem1 ;
	
	public void createControl(final ViewPart part,final CTabFolder tab) {
		if(dtab==null){
			//deley create control
			dtab=new MPEGConvertTab(tab,SWT.NULL);
			dtab.setViewPart(part);
			tabItem1.setControl(dtab);
		}
	}
	
	public void createTab(final ViewPart part,final CTabFolder tab) {
		tabItem1= new CTabItem(tab, SWT.NONE);
		tabItem1.setText("MPEG-Videos");
		tabItem1.setText(Messages.getString("dropsomething.mpegvideo"));
		
		
		fileOverwriteControler=new FileOverwriteControler(tab.getShell());
	}
	

	
	
	public class MPEGConvertTab extends DirectoryBasedDropSomething{

		private FFMpegExecuter ffmpegExecuter;

		private Label dragHere;

		private CCombo typeSelect;

		private Scale videoBitrateScale;

		private CCombo aspectRatio;
		
		
		private Button avisynth;
		private Button twoPass;
		private Button deinterlace;
		public MPEGConvertTab(Composite parent, int style) {
			super(parent, style);
			
			
		}

		public Composite createControls(Composite parent) {
			setPreferenceKey(MPEGCONVERT);
			
			SavePreferenceStore savePreference=new SavePreferenceStore();
			Composite composite=new Composite(parent,SWT.NULL);
			composite.setLayout(new GridLayout(1,true));
			
			
			createDirectoryInfo(composite);
			
			Composite bitrateSetting=new Composite(composite,SWT.NULL);
			bitrateSetting.setLayout(new GridLayout(4,true));
			Label videobitrate=new Label(bitrateSetting,SWT.NULL);
			
			
			videoBitrateScale = new Scale(bitrateSetting,SWT.NULL);
			videoBitrateScale.setMaximum(98);
			videoBitrateScale.setMinimum(1);
			//videoBitrateScale.setSelection(90);
			videoBitrateScale.addSelectionListener(savePreference);
			
			restoreControl(videoBitrateScale);//for label.
			
			UpdateVideoBitrateLabel updateVideoBitrateLabel=new UpdateVideoBitrateLabel(videobitrate,videoBitrateScale);
			updateVideoBitrateLabel.updateLabel();
			//videobitrate.setText(updateVideoBitrateLabel.toLabel(videoBitrateScale.getSelection()));
	
			
			//TODO keep last setting.
			typeSelect = new CCombo(composite,SWT.READ_ONLY);
			
			typeSelect.add(Messages.getString("dvd_720x480_mpeg2_ac3"));
			typeSelect.add(Messages.getString("dvd_352x240_mpeg2_ac3"));
			typeSelect.add(Messages.getString("dvd_720x480_mpeg2_mp2"));
			typeSelect.add(Messages.getString("dvd_352x240_mpeg2_mp2"));
			typeSelect.add(Messages.getString("dvd_352x240_mpeg1_mp2"));
			typeSelect.select(0);//default
			typeSelect.addSelectionListener(savePreference);
			
			twoPass = new Button(composite, SWT.CHECK);
			twoPass.setText(Messages.getString("mpegconvert.twopass"));
			//twoPass.setSelection(getPreferenceStore().getBoolean(PREFERENCE_TWO_PASS));
			twoPass.setToolTipText(Messages
					.getString("mpegconvert.twopass_tooltip"));
			twoPass.addSelectionListener(savePreference);
			
			
			avisynth = new Button(composite, SWT.CHECK);
			avisynth.setText(Messages.getString("flvconvert.use_avisynth"));
			//avisynth.setSelection(getPreferenceStore().getBoolean(PREFERENCE_AVISAYNTH));
			avisynth.setToolTipText(Messages
					.getString("flvconvert.use_avisynth_tooltip"));
			avisynth.addSelectionListener(savePreference);
			
			
			deinterlace = new Button(composite, SWT.CHECK);
			deinterlace.setText(Messages.getString("mpegconvert.deinterlace"));
			//twoPass.setSelection(getPreferenceStore().getBoolean(PREFERENCE_TWO_PASS));
			deinterlace.setToolTipText(Messages
					.getString("mpegconvert.deinterlace_tooltip"));
			deinterlace.addSelectionListener(savePreference);
			
			
			
			
			
			Composite aspectSetting=new Composite(composite,SWT.NULL);
			aspectSetting.setLayout(new GridLayout(2,false));
			Label aspectLabel=new Label(aspectSetting,SWT.NULL);
			aspectLabel.setText(Messages.getString("mpegconvert.aspect"));
			aspectRatio = new CCombo(aspectSetting,SWT.READ_ONLY);
			aspectRatio.add(FFMpegOptions.ASPECT_4x3);
			aspectRatio.add(FFMpegOptions.ASPECT_16x9);
			aspectRatio.select(0);
			aspectRatio.addSelectionListener(savePreference);
			aspectRatio.setToolTipText(Messages.getString("mpegconvert.aspect_tooltip"));
			dragHere=new Label(composite,SWT.NULL);
			dragHere.setLayoutData(new GridData(GridData.FILL_BOTH));
			
			
			//restore controls
			
			restoreControl(typeSelect);
			restoreControl(aspectRatio);
			restoreControl(avisynth);
			restoreControl(twoPass);
			restoreControl(deinterlace);
			//update status
			
			updateStatus();
			PlatformUI.getPreferenceStore().addPropertyChangeListener( new SettingMonitor());
			return composite;
		}
		
		public class SettingMonitor implements IPropertyChangeListener {

			public void propertyChange(PropertyChangeEvent event) {
				log.info(event.getProperty());
				if (event.getProperty().equals(FFMpegUI.FFMPEG_PATH)) {
					updateStatus();
				} 
			}
		}
		
public class SavePreferenceStore implements SelectionListener{
			
			public void widgetDefaultSelected(SelectionEvent e) {
				
			}

			public void widgetSelected(SelectionEvent e) {
				storeControl((Control)e.getSource());
			}
		}
		
		public void restoreControl(Control control){
			IPreferenceStore store=getPreferenceStore();
			
			if(control==avisynth){
				
				avisynth.setSelection(store.getBoolean(getPreferenceKey()+"."+AVISYNTH));
				
				}else if(control==typeSelect){
				selectCombo(typeSelect,store.getString(getPreferenceKey()+"."+TYPE_SELECT));
				}else if(control==aspectRatio){
					
					selectCombo(aspectRatio,store.getString(getPreferenceKey()+"."+ASPECT_RATIO));
					}else if(control==videoBitrateScale){
						log.info(getPreferenceKey()+"."+VIDEO_BITRATE+","+store.getInt(getPreferenceKey()+"."+VIDEO_BITRATE));
						videoBitrateScale.setSelection(store.getInt(getPreferenceKey()+"."+VIDEO_BITRATE));
				
				}else if(control==twoPass){
					
					twoPass.setSelection(store.getBoolean(getPreferenceKey()+"."+TWO_PASS));
				
					}else if(control==deinterlace){
						
						deinterlace.setSelection(store.getBoolean(getPreferenceKey()+"."+DEINTERLACE));
					
						}

			
		}
		
		public void selectCombo(CCombo combo,String value){
			int s=combo.getItemCount();
			for (int i = 0; i <s; i++) {
				if(combo.getItem(i).equals(value)){
					combo.select(i);
					break;
				}
			}
		}
		

		public void storeControl(Control control){
			IPreferenceStore store=getPreferenceStore();
			
			if(control==avisynth){
				
				
				store.setValue(getPreferenceKey()+"."+AVISYNTH, avisynth.getSelection());
				}else if(control==typeSelect){
				
				store.setValue(getPreferenceKey()+"."+TYPE_SELECT, typeSelect.getItem(typeSelect.getSelectionIndex()));
				}else if(control==aspectRatio){
					
					store.setValue(getPreferenceKey()+"."+ASPECT_RATIO, aspectRatio.getItem(aspectRatio.getSelectionIndex()));
					}else if(control==videoBitrateScale){
				
				store.setValue(getPreferenceKey()+"."+VIDEO_BITRATE, videoBitrateScale.getSelection());
				}else if(control==twoPass){
					
					
					store.setValue(getPreferenceKey()+"."+TWO_PASS, twoPass.getSelection());
					}else if(control==deinterlace){
						
						
						store.setValue(getPreferenceKey()+"."+DEINTERLACE, deinterlace.getSelection());
						}
		}
		

		
		public class UpdateVideoBitrateLabel implements SelectionListener{
			private Label label;
			private Scale scale;
			public UpdateVideoBitrateLabel(Label label,Scale scale){
				this.label=label;
				this.scale=scale;
				scale.addSelectionListener(this);
			}
			public void widgetDefaultSelected(SelectionEvent e) {
				
			}

			public void widgetSelected(SelectionEvent e) {
				updateLabel();
			}
			public void updateLabel(){
				int value=scale.getSelection();
				label.setText(toLabel(value));
			}
			
			public String toLabel(int value){
				String label=Messages.getString("mpegconver.video_bitrate")+" ";
				label+=(value*100)+" k/bps";
				
				double mega=((double)value*100+256)*1000/8/1024/1024;//256=audio
				//log.info(mega);
				int mega_hour=(int) (mega*60*60);
				//log.info(mega_hour);
				String tmpV=""+(mega_hour);
				//String megalabel=tmpV.substring(0,1)+"."+tmpV.substring(1);
				String description="";
				description+=15+" "+Messages.getString("MPEGConvertTab.minute")+" = "+(int)(mega*15*60)+"MB"+"\n";
				description+=30+" "+Messages.getString("MPEGConvertTab.minute")+" = "+(int)(mega*30*60)+"MB"+"\n";
				description+=45+" "+Messages.getString("MPEGConvertTab.minute")+" = "+(int)(mega*45*60)+"MB"+"\n";
				description+=1+" "+Messages.getString("MPEGConvertTab.hour")+" = "+tmpV+"MB"+"\n";
				description+=1+" "+Messages.getString("MPEGConvertTab.hour")+" "+30+" "+Messages.getString("MPEGConvertTab.minute")+" = "+(int)(mega*90*60)+"MB"+"\n";
				description+=1+" "+Messages.getString("MPEGConvertTab.hour")+" "+45+" "+Messages.getString("MPEGConvertTab.minute")+" = "+(int)(mega*105*60)+"MB"+"\n";
				description+=2+" "+Messages.getString("MPEGConvertTab.hour")+" = "+(int)(mega*120*60)+"MB"+"\n";
				
				description+="4.4G DVD = "+toTime(videoBitrateScale.getSelection()*1000*100+(256*1000),(int)(1024*4.30));
				scale.setToolTipText(description);
				return label;
			}
			
		}
		
		public String toTime(long bps,long maxMega){
			long bytes=bps/8;
			
			long second=maxMega*1024*1024/bytes;
			long hour=second/3600;
			second=second%3600;
			long min=second/60;
			long sec=second%60;
			
			String hstring=""+hour;
			if(hstring.length()<2){
				hstring="0"+hstring;
			}
			
			String mstring=""+min;
			if(mstring.length()<2){
				mstring="0"+mstring;
			}
			
			String sstring=""+sec;
			if(sstring.length()<2){
				sstring="0"+sstring;
			}
			return hstring+":"+mstring+":"+sstring;
		}

		public void inconvert(File file) {
			ffmpegExecuter.execute(new File[]{file});
		}

		public void beforeConvert() {
			ffmpegExecuter = new FFMpegExecuter();
			
			ffmpegExecuter.setExecuteListener(new FFMpegMonitor());
			
			String ffmpegPath = FFMpegUI.getFFmpeg();
			FFMpegPreference preference=ffmpegExecuter.getFfmpegPreference();
			preference.setFfmpegPath(ffmpegPath);
			preference.setExtension(FFMpegOptions.EXTENSION_MPEG);
			
			
			ffmpegExecuter.setSameDirectory(samefolder.getSelection());
			ffmpegExecuter.setBackup(backup.getSelection());
			if(!samefolder.getSelection()){
				ffmpegExecuter.setExportDir(directoryChooser.getAbsoluteFilePath());
			}
			
			ffmpegExecuter.setUseAvisynth(avisynth.getSelection());
			//TODO:change them.
			int videoBitrate=videoBitrateScale.getSelection()*100;
			//int videoBitrate=9000;
			
			if(twoPass.getSelection()){
				preference.setHighQuality(true);//two pass use high quority
				preference.setTwoPassEncode(true);
			}
			
			if(deinterlace.getSelection()){
				
				preference.setDeinterlace(true);
			}
			
			int audioBitrate=256;
			//copy setting.
			String selectlabel=typeSelect.getItem(typeSelect.getSelectionIndex());
			if(selectlabel.equals(Messages.getString("dvd_352x240_mpeg1_mp2"))){
				preference.setTarget(FFMpegOptions.TARGET_NTSC_DVD);
				preference.setVideoSize("352x240");
				preference.setVideoRate(29.97);
				preference.setVideoCodec("mpeg1video");
				preference.setVideoAspect(aspectRatio.getItem(aspectRatio.getSelectionIndex()));
				preference.setVideoBitrate(videoBitrate);
				preference.setVideoMaxBitrate(videoBitrate);
				preference.setVideoMinBitrate(videoBitrate);
				
				preference.setAudioCodec("mp2");
				preference.setAudioRate(48000);
				preference.setAudioChannel(2);
				preference.setAudioBitrate(audioBitrate);
			}else if(selectlabel.equals(Messages.getString("dvd_720x480_mpeg2_ac3"))){
				preference.setTarget(FFMpegOptions.TARGET_NTSC_DVD);
				preference.setVideoSize("720x480");
				preference.setVideoRate(29.97);
				preference.setVideoCodec("mpeg2video");
				preference.setVideoAspect(aspectRatio.getItem(aspectRatio.getSelectionIndex()));
				preference.setVideoBitrate(videoBitrate);
				//preference.setVideoMaxBitrate(videoBitrate);
				//preference.setVideoMinBitrate(videoBitrate);
				
				preference.setAudioCodec("ac3");
				preference.setAudioRate(48000);
				preference.setAudioChannel(2);
				preference.setAudioBitrate(audioBitrate);
				
				
			}else if(selectlabel.equals(Messages.getString("dvd_352x240_mpeg2_ac3"))){
				preference.setTarget(FFMpegOptions.TARGET_NTSC_DVD);
				preference.setVideoSize("352x240");
				preference.setVideoRate(29.97);
				preference.setVideoCodec("mpeg2video");
				preference.setVideoAspect(aspectRatio.getItem(aspectRatio.getSelectionIndex()));
				preference.setVideoBitrate(videoBitrate);
				//preference.setVideoMaxBitrate(videoBitrate);
				//preference.setVideoMinBitrate(videoBitrate);
				
				preference.setAudioCodec("ac3");
				preference.setAudioRate(48000);
				preference.setAudioChannel(2);
				preference.setAudioBitrate(audioBitrate);
			}else if(selectlabel.equals(Messages.getString("dvd_352x240_mpeg2_mp2"))){
				preference.setTarget(FFMpegOptions.TARGET_NTSC_DVD);
				preference.setVideoSize("352x240");
				preference.setVideoRate(29.97);
				preference.setVideoCodec("mpeg2video");
				preference.setVideoAspect(aspectRatio.getItem(aspectRatio.getSelectionIndex()));
				preference.setVideoBitrate(videoBitrate);
				//preference.setVideoMaxBitrate(videoBitrate);
				//preference.setVideoMinBitrate(videoBitrate);
				
				preference.setAudioCodec("mp2");
				preference.setAudioRate(48000);
				preference.setAudioChannel(2);
				preference.setAudioBitrate(audioBitrate);
			}else if(selectlabel.equals(Messages.getString("dvd_720x480_mpeg2_mp2"))){
				preference.setTarget(FFMpegOptions.TARGET_NTSC_DVD);
				preference.setVideoSize("720x480");
				preference.setVideoRate(29.97);
				preference.setVideoCodec("mpeg2video");
				preference.setVideoAspect(aspectRatio.getItem(aspectRatio.getSelectionIndex()));
				preference.setVideoBitrate(videoBitrate);
				//preference.setVideoMaxBitrate(videoBitrate);
				//preference.setVideoMinBitrate(videoBitrate);
				
				preference.setAudioCodec("mp2");
				preference.setAudioRate(48000);
				preference.setAudioChannel(2);
				preference.setAudioBitrate(audioBitrate);
				
				
			}
			
			
		
			
			//set max bitrate otherwise error happens.
			if(videoBitrate>9000){//9000 is default
				preference.setVideoMaxBitrate(videoBitrate);
			}
			
//			support thread.
			boolean threads = FFMpegUI.isUseThread();
			if(threads){
				/*it crush easily still rev9200*/ 
				//preference.setThreads(2);
			}
			
		}

		public void afterConvert() {
			// TODO Auto-generated method stub
			
		}
		
		public class FFMpegMonitor implements DirectryBasedExecuterListener{

			public void beforeConvert() {
				// TODO Auto-generated method stub
				
			}

			public void afterConvert() {
				// TODO Auto-generated method stub
				
			}

			public void startConvert(File file) {
				// TODO Auto-generated method stub
				
			}

			public void endConvert(File file) {
				Akj_betasPlugin.getDefault().getProcessPrinter().printOutput("[complete:mpeg]"+file.getAbsolutePath()+"\n\n");
			}

			public void faildConvert(File file, String message) {
				Akj_betasPlugin.getDefault().getProcessPrinter().printOutput("[faild:mpeg]"+message+","+file.getAbsolutePath()+"\n\n");
			}

			public void printProcess(String line) {
				//Akj_betasPlugin.getDefault().
				Akj_betasPlugin.getDefault().getProcessPrinter().printError(line);
			}

			public boolean askOverwrite(File output) {
				
				return FileOverwriteControler.askOverwrite(fileOverwriteControler,output);
			}
			
		}
		//overwrite only work when ffmpeg is available
		public boolean isCanConvert(){
			
			String ffmpegPath = FFMpegUI.getFFmpeg();

			if (!FFMpegUtils.isFFMpegAvailable(ffmpegPath)) {
			return false;
			}
			return super.isCanConvert();
		}

		public void cancelConvert() {
			ffmpegExecuter.cancel();
		}

		public void updateStatus() {
			
			if(samefolder.getSelection() || directoryChooser.getFile()!=null){
				setMessage(Messages.getString("dropsomething.drag_folder"));
				setCanConvert(true);
			}else{
				setErrorMessage(Messages.getString("dropsomething.choose_folder"));
				setCanConvert(false);
			}
			log.info("canConvert:"+isCanConvert());
		}
		
		public void setMessage(String text){
			if(dragHere!=null){//before initialize
			dragHere.setForeground(new Color(null,64,255,64));
			dragHere.setText(text);
			}
		}
		public void setErrorMessage(String text){
			if(dragHere!=null){
			dragHere.setForeground(new Color(null,255,0,0));
			dragHere.setText(text);
			}
		}

		public IPreferenceStore getPreferenceStore(){
			return Akj_betasPlugin.getDefault().getPreferenceStore();
		}
		
	}
	
}
